package com.shuwen.gcdj.common.util;

import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class StreamUtil {
    private StreamUtil() {
    }

    public static <T, R> List<R> mapList(Collection<T> datas, Function<T, R> mapFunction) {
        return (List) (CollectionUtils.isEmpty(datas) ? new ArrayList() : (List) datas.stream().map(mapFunction).collect(Collectors.toList()));
    }

    public static <T, R> Set<R> map2set(Collection<T> datas, Function<T, R> mapFunction) {
        return (Set) (CollectionUtils.isEmpty(datas) ? new HashSet() : (Set) datas.stream().map(mapFunction).collect(Collectors.toSet()));
    }

    public static <T> List<T> filterList(Collection<T> datas, Predicate<T> filterFunction) {
        return (List) (CollectionUtils.isEmpty(datas) ? new ArrayList() : (List) datas.stream().filter(filterFunction).collect(Collectors.toList()));
    }

    public static <T, R, A> Map<R, A> list2map(Collection<T> datas, Function<T, R> mapKey, Function<T, A> mapValue) {
        return (Map) datas.stream().collect(Collectors.toMap(mapKey, mapValue, (key1, key2) -> {
            return key2;
        }));
    }

    public static <T, R> Map<R, T> list2map(Collection<T> datas, Function<T, R> mapKey) {
        return (Map) datas.stream().collect(Collectors.toMap(mapKey, Function.identity(), (key1, key2) -> {
            return key2;
        }));
    }

    public static <K, V> Map<K, V> filterMap(Map<K, V> map, final Predicate<? super V> valuePredicate) {
        if (map == null) {
            return Collections.emptyMap();
        } else {
            Objects.requireNonNull(valuePredicate);
            return Maps.filterValues(map, valuePredicate::test);
        }
    }

    public static <K, V> Map<K, V> filterNotNullValueMap(Map<K, V> map) {
        return filterMap(map, Objects::nonNull);
    }
}